#include <p33fj256gp506.h>
#include "delays.h"

// FRC Oscillator
_FOSCSEL(FNOSC_FRC);					

// Clock Switching is enabled and Fail Safe Clock Monitor is disabled
// OSC2 Pin Function: OSC2 is Clock Output
// Primary Oscillator Mode: Disabled
_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF  & POSCMD_XT);

// Watchdog Timer Enabled/disabled by user software
// (LPRC can be disabled by clearing SWDTEN bit in RCON register
_FWDT(FWDTEN_OFF);              

volatile int minCounter = 0;
volatile int pwmDC = 624;

int main (void)
{
	// Set-up clock to 40 MIPS
	// Configure PLL prescaler, PLL postscaler, PLL divisor
	// Configure Oscillator to operate the device at 40Mhz
	// Fosc = Fin*M/(N1*N2), Fcy=Fosc/2
	// Fosc = 8M*40/(2*2) = 80Mhz for 8M input clock
    
    PLLFBD = 38;						// M=40

    CLKDIVbits.PLLPOST = 0;        		// N1=2
    CLKDIVbits.PLLPRE = 0;        		// N2=2
    OSCTUN = 0;                    		// Tune FRC oscillator, if FRC is used

	// Disable Watch Dog Timer
    RCONbits.SWDTEN = 0;

	// Clock switching to incorporate PLL
    __builtin_write_OSCCONH(0x03);      // Initiate Clock Switch to Primary

    // Oscillator with PLL (NOSC=0b011)                                                
    __builtin_write_OSCCONL(0x01);      // Start clock switching
    
    while (OSCCONbits.COSC != 0b011);   // Wait for Clock switch to occur

	// Wait for PLL to lock
    while(OSCCONbits.LOCK!=1) {};

 	// Set up I/O Port
 	ADPCFG=0xFFFF;                  	// Analog ports as Digital I/O
 	TRISD=0xFFFC;                   	// PD0:PD1 as output pins
    LATD=0x0000;                    	// Initial Value of 0

	InitPWM();

 	// Main Program Loop
	while(1)
	{
		PORTDbits.RD1 = 1;
		delay_ms(1500);
		PORTDbits.RD1 = 0;
		delay_ms(1500);
	}
 
 	return(0);
}
	
void InitPWM (void)
{
	// Inicializacion del modulo
	OC1CONbits.OCM = 0b000; 			// Deshabilito el OC
	OC1R = 100;             			// Le doy el valor del primer dc 
	OC1RS = 0x270;            
	
	OC1CONbits.OCTSEL = 0; 				// TMR2 sera nuestra base de tiempos
	OC1R = 100;             			
	OC1CONbits.OCM = 0b110; 			// Seleccionamos pwm sin proteccion de fallas

	T2CONbits.TON = 0;      			// Deshabilito el tmr
	T2CONbits.TCS = 0;      			// Fuente de clock interna
	T2CONbits.TGATE = 0;    
	T2CONbits.TCKPS = 0b10; 			// 1:1 Prescaler
	TMR2 = 0x00;            			// Limpio el regitro del timer
	PR2 = 0x30D3;              			// Cargo la cuenta del periodo: PWM Period = [PRy + 1] * TCy * Prescaler => PRy = ( 20ms / (1 / 40Mhz) * 64 ) - 1
	IPC1bits.T2IP = 0x01;   			// Prioridad de interrupcion
	IFS0bits.T2IF = 0;      			// Limpio el flag de interrupcion
	IEC0bits.T2IE = 1;      			// Habilito interrupciones
	T2CONbits.TON = 1;      			// Inicio el timer

	return;
}

void __attribute__((__interrupt__)) _T2Interrupt (void)
{
	if (minCounter++ == 5)
 	{
		pwmDC += 30;
		minCounter = 0;
		
		if (pwmDC >= 1260)
        {
			pwmDC = 624;
			
		}
	}

	OC1RS = pwmDC;
 	IFS0bits.T2IF = 0;      			// Limpio el flag
}                                                                